﻿#include "CImgEnhance.h"
#include <QDebug>
#include "SIMD/vectormath_exp.h"
CImgEnhance::CImgEnhance()
{
    // 幂变换映射表
    powerTransfTable = new uchar[256]{0}; // 0-255
    revseTransfTable = new uchar[256]{0};
    logTransfTable = new uchar[256]{0};
}

CImgEnhance::~CImgEnhance()
{
    delete [] powerTransfTable;
    delete [] revseTransfTable;
    delete [] logTransfTable;
}

/**
 * @brief 构建幂变换查找表
 * @param fc    亮度
 * @param fg    对比度
 * @return
 */
void CImgEnhance::power_tableBuild(float fc, float fg)
{
    // 幂变换
    float rPix = 0;
    float sPix = 0;
    for(int i=0;i<256;i++){
        // 归一化
        rPix = i/255.0f;
        // 幂变换
        sPix = fc * pow(rPix,fg);
        if(sPix>1.0f) sPix = 1.0f;
        powerTransfTable[i] = uchar(sPix*255);
    } 
}

/**
 * @brief 幂变换   s = c * r^y
 * @param src   原图
 * @param dst   处理图
 * @param fc
 * @param fg
 * @return true success
 */
bool CImgEnhance::power_transform(cv::Mat &src, cv::Mat &dst, float fc, float fg)
{
    // 图像的尺寸大小相同
    if((src.cols!=dst.cols)||(src.rows!=dst.rows)){
        qDebug() << "输入和输出的图像的尺寸不一致";
        return false;
    }
    // fc > 0  fg > 0
    if (fg <= 0) {
        qDebug() << "Invaild fg";
        return false;
    }
    if (fc <= 0) {
        qDebug() << "Invaild fg";
        return false;
    }
    // 构建幂变换像素映射表
    power_tableBuild(fc,fg);
    int cols = src.cols;
    int rows = src.rows;
    // 幂变换
    for(int y=0;y<rows;y++){
        uchar *srcDta = src.ptr<uchar>(y);
        uchar *dstDta = dst.ptr<uchar>(y);
        for(int x=0;x<cols;x++){
            dstDta[x] = powerTransfTable[srcDta[x]];
        }
    }
    return true;
}

/**
 * @brief 构建取反变换查找表
 */
void CImgEnhance::reverse_tableBuild()
{
    int rev = 0,i=0;
    for(i=0;i<256;++i){
        rev = 255 - i;
        *(revseTransfTable+i)= uchar(rev);
    }
}

/**
 * @brief 取反变换
 * @param src   原图
 * @param dst   处理图
 * @return
 */
bool CImgEnhance::reverse_transform(cv::Mat &src, cv::Mat &dst)
{
    // 图像的尺寸大小相同
    if((src.cols!=dst.cols)||(src.rows!=dst.rows)){
        qDebug() << "输入和输出的图像的尺寸不一致";
        return false;
    }
    // 构建取反表
    reverse_tableBuild();
    // 取反变换
    int cols = dst.cols;
    int rows = dst.rows;
    for(int y=0;y<rows;++y){
        uchar *dataDst = dst.ptr<uchar>(y);
        uchar *dataSrc = src.ptr<uchar>(y);
        for(int x=0;x<cols;++x){
            dataDst[x] = revseTransfTable[dataSrc[x]];
        }
    }

    return true;
}

// 直方图均衡化
bool CImgEnhance::HistEqualization(cv::Mat& mInput, cv::Mat& mOutput) {
    int iRows = mInput.rows;
    int iCols = mInput.cols;
    int iPixNumTable[256] = { 0 }; // 存放每个像素的出现次数
    // 统计每个元素的出现次数
    for (int y = 0; y < iRows; y++) {
        uchar* data = mInput.ptr<uchar>(y); // 第y行首地址
        for (int x = 0; x < iCols; x++) {
            iPixNumTable[data[x]]++;
        }
    }
    int iPixSum = iRows * iCols; // 整幅图像的像素数量
    double dTemp = 0;
    double dPixCumRatio[256] = { 0 }; // 存放每个像素对应的累计比例
    for (int i = 0; i < 256; i++) {
        dTemp += (double)iPixNumTable[i] / iPixSum; // 数据类型一定要转换！！
        dPixCumRatio[i] = dTemp;
    }
    // 直方图均衡化
    for (int y = 0; y < iRows; y++) {
        uchar* ptrOutput = mOutput.ptr<uchar>(y);
        uchar* ptrIutput = mInput.ptr<uchar>(y);
        for (int x = 0; x < iCols; x++) {
            ptrOutput[x] = 255 * dPixCumRatio[ptrIutput[x]];
        }
    }
    return true; // true 1 false 0
}

/**
 * @brief 构建对数变换查找表
 * @param fc
 * @return
 */
bool CImgEnhance::log_tableBuild(float fc)
{
    // s = c * log(1 + r)
    if(fc <= 0){
        qDebug() << "Invalid fc";
        return false;
    }
    for(int i = 0; i < 256; ++i){
        float r = float(i) / 255.0f;  // 归一化到[0,1]
        float s = fc * log(1.0f + r); // 正确应用对数变换公式

        // 限制到[0,1]范围并转换为uchar
        s = std::max(0.0f, std::min(s, 1.0f));
        logTransfTable[i] = uchar(255 * s + 0.5f); // 添加0.5f用于四舍五入
    }
    return true;
}

/**
 * @brief 对数变换
 * @param src   原图
 * @param dst   处理图
 * @return
 */
bool CImgEnhance::log_transform(cv::Mat &src, cv::Mat &dst,float fc)
{
    // 图像的尺寸大小相同
    if((src.cols!=dst.cols)||(src.rows!=dst.rows)){
        qDebug() << "输入和输出的图像的尺寸不一致";
        return false;
    }
    // 构建对数查找表
    log_tableBuild(fc);
    // 对数变换
    int cols = dst.cols;
    int rows = dst.rows;
    for(int y=0;y<rows;++y){
        uchar *dataDst = dst.ptr<uchar>(y);
        uchar *dataSrc = src.ptr<uchar>(y);
        for(int x=0;x<cols;++x){
            dataDst[x] = logTransfTable[dataSrc[x]];
        }
    }

    return true;
}

//------------------------------------------------------------------------SIMD复现
// TODO
/**
 * @brief 构建幂变换像素映射表
 * @param fc    亮度
 * @param fg    对比度
 * @return
 */
void CImgEnhance::power_tableBuildSIMD(float fc, float fg)
{
    // 确保包含正确的头文件
    #include "vectormath_exp.h"

    // 每次处理8个像素(使用Vec8f单精度浮点向量)
    for (int i = 0; i < 256; i += 8) {
        // 创建索引向量[i, i+1, ..., i+7]
        Vec8i indices(i, i+1, i+2, i+3, i+4, i+5, i+6, i+7);

        // 将索引转为浮点并归一化到[0,1]
        Vec8f rPix = to_float(indices) * (1.0f / 255.0f);

        // 计算幂变换: fc * rPix^fg
        Vec8f sPix = fc * pow(rPix, fg);    // #include "SIMD/vectormath_exp.h"

        // 限制到[0,1]范围并转为uchar
        sPix = min(sPix, 1.0f);
        Vec8i result = truncatei(sPix * 255.0f);

        // 存储结果到查找表
        for (int j = 0; j < 8 && (i+j) < 256; j++) {
            powerTransfTable[i+j] = (uchar)result[j];
        }
    }
}

/**
 * @brief SIMD 幂变换   s = c * r^y
 * @param src   原图
 * @param dst   处理图
 * @param fc    亮度
 * @param fg    对比度
 * @return true success
 */
bool CImgEnhance::power_transformSIMD(cv::Mat &src, cv::Mat &dst, float fc, float fg)
{
    // 输入验证
    if ((src.cols != dst.cols) || (src.rows != dst.rows)) {
        qDebug() << "输入输出图像尺寸不匹配";
        return false;
    }

    if (fg <= 0 || fc <= 0) {
        qDebug() << "参数无效(必须大于0)";
        return false;
    }
    // 使用SIMD构建查找表
    power_tableBuildSIMD(fc, fg);

    // 加载查找表到SIMD向量
    Vec32uc tableVec;
    tableVec.load(powerTransfTable);

    int cols = src.cols;
    int rows = src.rows;
    // 每次处理32个像素(使用Vec32uc)
    for (int y = 0; y < rows; y++) {
        const uchar* srcData = src.ptr<uchar>(y);
        uchar* dstData = dst.ptr<uchar>(y);

        int x = 0;
        // 每次处理32像素
        for (; x <= cols - 32; x += 32) {
            // 加载32像素
            Vec32uc srcVec;
            srcVec.load(srcData + x);

            // 查找变换后的值
            Vec32uc dstVec = Vec32uc(lookup32(srcVec, tableVec));

            // 存储结果
            dstVec.store(dstData + x);
        }

        // 处理剩余像素
        for (; x < cols; x++) {
            dstData[x] = powerTransfTable[srcData[x]];
        }
    }

    return true;
}


